package com.zeus.gateway.oauth2Config;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Set;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;

/**
 * @Author fangyi
 * @Date 2023/7/15 23:07
 * @Version 1.0
 */

//进行我们访问的拦截

@Component
public class AccessManager implements ReactiveAuthorizationManager<AuthorizationContext> {

    private Set<String> permmitAll = new ConcurrentSkipListSet<>();

    private static final AntPathMatcher antPathMatcher = new AntPathMatcher();

    public AccessManager(){
        permmitAll.add("/**/oauth/**");
    }

    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext authorizationContext) {

        ServerWebExchange exchange = authorizationContext.getExchange();
        String requestUrl = exchange.getRequest().getURI().getPath();

        return authentication.map(auth -> {
            if(checkPath(requestUrl)){
                return new AuthorizationDecision(true);
            }
            if(auth instanceof OAuth2Authentication){
                OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) auth;
                String clientId = oAuth2Authentication.getOAuth2Request().getClientId();
                if(StringUtils.isNotEmpty(clientId)){
                    return new AuthorizationDecision(true);
                }
            }
            return new AuthorizationDecision(false);
        });
    }

    private boolean checkPath(String requestUrl) {
        return permmitAll.stream().
                filter(p-> antPathMatcher.match(p,requestUrl)).findFirst().isPresent();
    }
}
